﻿using SchemaExplorer;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace BaoMen.CodeSmith.Framework
{
    /// <summary>
    /// 通用帮助类
    /// </summary>
    public class Util
    {
        #region 
        /// <summary>
        /// 移除字符串的前缀(不区分大小写)
        /// </summary>
        /// <param name="str"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public static string RemovePrefix(string str, string prefix)
        {
            if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(prefix) || !str.ToLower().StartsWith(prefix.ToLower()))
                return str;
            else
                return str.Substring(prefix.Length);
        }

        /// <summary>
        /// 移除字符串的分隔符，并返回Pascal命名法命名的字串
        /// </summary>
        /// <param name="name"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static string RemoveSeparator(string name, string separator)
        {
            if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(separator)) return name;
            string[] tempString = name.Split(separator.ToCharArray());
            for (int i = 0; i < tempString.Length; i++)
            {
                tempString[i] = ToPascalCase(tempString[i]);
                //tempString[i] = char.ToUpper(tempString[i][0]) + tempString[i].Substring(1).ToLower();
            }
            return string.Join("", tempString);
        }


        #endregion

        #region camel or pascal case
        /// <summary>
        /// 转为Camel命名规范（首字母小写）
        /// </summary>
        /// <param name="word">单词</param>
        /// <returns></returns>
        public static string ToCamelCase(string word)
        {
            if (string.IsNullOrEmpty(word)) return word;
            if (char.IsUpper(word[0]))
            {
                char[] chars = word.ToCharArray();
                chars[0] = char.ToLower(chars[0]);
                //for (int i = 1, j = 2; i < chars.Length; i++, j++)
                //{
                //    if (char.IsUpper(chars[i]) && ((j < chars.Length && char.IsUpper(chars[j])) || j == chars.Length))
                //        chars[i] = char.ToLower(chars[i]);
                //    else
                //        break;
                //}
                return new string(chars);
            }
            else
                return word;
            //string camelCaseString = char.ToLower(str[0]).ToString();
            //if (str.Length > 1)
            //    camelCaseString += str.Substring(1);
            //return camelCaseString;
        }

        /// <summary>
        /// 转为Camel命名规范（首字母小写）
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="separator">分隔符</param>
        /// <returns></returns>
        public static string ToCamelCase(string str, char separator)
        {
            if (string.IsNullOrEmpty(str)) return str;
            string[] strs = str.ToLower().Split(separator);
            StringBuilder sb = new StringBuilder();
            sb.Append(strs[0]);
            for (int i = 1; i < strs.Length; i++)
            {
                sb.Append(ToPascalCase(strs[i]));
            }
            return sb.ToString();
        }

        /// <summary>
        /// 转为Pascal命名规范（首字母大写）
        /// </summary>
        /// <returns></returns>
        public static string ToPascalCase(string word)
        {
            if (string.IsNullOrEmpty(word)) return word;
            if (char.IsLower(word[0]))
            {
                char[] chars = word.ToCharArray();
                chars[0] = char.ToUpper(chars[0]);
                return new string(chars);
            }
            else
                return word;
        }

        /// <summary>
        /// 转为Pascal命名规范（首字母大写）
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="separator">分隔符</param>
        /// <returns></returns>
        public static string ToPascalCase(string str, char separator)
        {
            if (string.IsNullOrEmpty(str)) return str;
            string[] strs = str.ToLower().Split(separator);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < strs.Length; i++)
            {
                sb.Append(ToPascalCase(strs[i]));
            }
            return sb.ToString();
        }
        #endregion

        #region map dbtype to c# type
        /// <summary>
        /// 获取C#非空类型
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public static string GetCSharpNotNullTypeName(ColumnSchema column)
        {
            switch (column.DataType)
            {
                case DbType.AnsiString: return "string";
                case DbType.AnsiStringFixedLength: return "string";
                case DbType.Binary: return "byte[]";
                case DbType.Boolean: return "bool";
                case DbType.Byte: return "byte";
                case DbType.Currency: return "decimal";
                case DbType.Date: return "DateTime";
                case DbType.DateTime: return "DateTime";
                case DbType.Decimal: return "decimal";
                case DbType.Double: return "double";
                case DbType.Guid: return "Guid";
                case DbType.Int16: return "short";
                case DbType.Int32: return "int";
                case DbType.Int64: return "long";
                case DbType.Object:
                    if (column.NativeType == "json")
                    {
                        return "string";
                    }
                    return "object";
                case DbType.SByte: return "sbyte";
                case DbType.Single: return "float";
                case DbType.String: return "string";
                case DbType.StringFixedLength: return "string";
                case DbType.Xml: return "string";
                case DbType.Time: return "TimeSpan";
                case DbType.UInt16: return "ushort";
                case DbType.UInt32: return "uint";
                case DbType.UInt64: return "ulong";
                case DbType.VarNumeric:
                    if (column.Scale == 0)
                    {
                        if (column.Precision <= 4)
                        {
                            return "short";
                        }
                        else if (column.Precision <= 9)
                        {
                            return "int";
                        }
                        else if (column.Precision <= 18)
                        {
                            return "long";
                        }
                        else
                        {
                            goto default;
                        }
                    }
                    else
                    {
                        return "decimal";
                    }
                default:
                    {
                        return "__UNKNOWN__" + column.NativeType;
                    }
            }
        }

        /// <summary>
        /// 获取C#可空类型
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public static string GetCSharpNullableTypeName(ColumnSchema column)
        {
            switch (column.DataType)
            {
                case DbType.AnsiString: return "string";
                case DbType.AnsiStringFixedLength: return "string";
                case DbType.Binary: return "byte[]";
                case DbType.Boolean: return "bool?";
                case DbType.Byte: return "byte?";
                case DbType.Currency: return "decimal?";
                case DbType.Date: return "DateTime?";
                case DbType.DateTime: return "DateTime?";
                case DbType.Decimal: return "decimal?";
                case DbType.Double: return "double?";
                case DbType.Guid: return "Guid?";
                case DbType.Int16: return "short?";
                case DbType.Int32: return "int?";
                case DbType.Int64: return "long?";
                case DbType.Object:
                    //if (column.ExtendedProperties.Contains("CS_ColumnType") && column.ExtendedProperties["CS_ColumnType"].Name == "JSON")
                    //{
                    //    return "string";
                    //}
                    if (column.NativeType == "json")
                    {
                        return "string";
                    }
                    return "object";
                case DbType.SByte: return "sbyte?";
                case DbType.Single: return "float?";
                case DbType.String: return "string";
                case DbType.StringFixedLength: return "string";
                case DbType.Xml: return "string";
                case DbType.Time: return "TimeSpan";
                case DbType.UInt16: return "ushort?";
                case DbType.UInt32: return "uint?";
                case DbType.UInt64: return "ulong?";
                case DbType.VarNumeric:
                    if (column.Scale == 0)
                    {
                        if (column.Precision <= 4)
                        {
                            return "short?";
                        }
                        else if (column.Precision <= 9)
                        {
                            return "int?";
                        }
                        else if (column.Precision <= 18)
                        {
                            return "long?";
                        }
                        else
                        {
                            goto default;
                        }
                    }
                    else
                    {
                        return "decimal?";
                    }
                default:
                    {
                        return "__UNKNOWN__" + column.NativeType;
                    }
            }
        }
        #endregion
    }
}
